#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#include <dirent.h>
#include <sys/time.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/socket.h>

#include "data_type.h"
#include "alloc.h"
#include "memfunc.h"
#include "basefunc.h"
#include "struct_deal.h"
#include "crypto_func.h"
#include "memdb.h"
#include "message.h"
#include "ex_module.h"
#include "sys_func.h"
#include "return_value.h"
#include "tcm_constants.h"
#include "tcm_structures.h"
#include "tcmfunc.h"
#include "tcm_cube_struct.h"
#include "tcm_key_manage.h"
#include "tcm_key_desc.h"
#include "tcm_pik_desc.h"
#include "file_struct.h"

#include <sys/types.h>

#include "tcmkey_verify.h"


BYTE Buf[DIGEST_SIZE*16];
int tcmkey_verify_init(void * sub_proc,void * para)
{
	int ret;
	// add youself's plugin init func here
	return 0;
}

int tcmkey_verify_start(void * sub_proc,void * para)
{
	int ret;
	void * recv_msg;
	int i;
	int type;
	int subtype;


	while(1)
	{
		sleep(5);
		ret=ex_module_recvmsg(sub_proc,&recv_msg);
		if(ret<0)
			continue;
		if(recv_msg==NULL)
			continue;
		type=message_get_type(recv_msg);
		subtype=message_get_subtype(recv_msg);
		if((type==TYPE(GENERAL_RETURN)) && (subtype==SUBTYPE(GENERAL_RETURN,UUID))&&(message_get_flag(recv_msg) &MSG_FLAG_SIGN))
		{
			ret = proc_tcm_verify_message(sub_proc,recv_msg);
		}
    // else if((type == TYPE(VTCM_IN_KEY)) && (subtype == SUBTYPE(VTCM_IN_KEY,TCM_BIN_PUBKEY)))
    // {
    //     ret = proc_memstore_pubkey(sub_proc, recv_msg);
    // }
	}
	return 0;


};

int proc_tcm_verify_message(void * sub_proc,void * message)
{
        int i;
        int ret;

        BYTE blob[32];
        int blob_size = 8;
        int flag;

	    MSG_EXPAND * msg_expand;
	    RECORD(GENERAL_RETURN,UUID)* uuid_record;
	    RECORD(GENERAL_RETURN,BINDATA)* sign_data;
	    RECORD(GENERAL_RETURN,INT)* verify_data;
     RECORD(VTCM_IN_KEY,TCM_BIN_PUBKEY) * tcm_pubkey_1;
	  RECORD(FILE_TRANS,FILE_DATA) * file_data;

       // TCM_PUBKEY * pubkey;
	    BYTE Namebuf[DIGEST_SIZE*4];
	    char uuid[DIGEST_SIZE*2+1];

    // get uuid
	//ret=message_remove_expand(message,TYPE_PAIR(GENERAL_RETURN,UUID),&msg_expand);
	ret=message_get_record(message,&uuid_record,0);
	if(ret<0)
		return ret;
	//uuid_record=msg_expand->expand;

    ret=message_get_expand(message,&msg_expand,0);
	if(ret<0)
		return ret;
    file_data = msg_expand->expand;


    int count = 0;
  while(file_data->filename[count] != '\0'){
    blob[count] = (BYTE)file_data->filename[count];
	count++;
  }
    blob_size = count;

    // get signdata
	ret=message_get_expand(message,&msg_expand,1);
	if(ret<0)
		return ret;
	sign_data=msg_expand->expand;

  //   // get pubkey file name
  //   Memset(Namebuf,0,DIGEST_SIZE*3);
	// Strcpy(Namebuf,"pubkey/");
	// //digest_to_uuid(a,Namebuf+Strlen(Namebuf));
	// Strcat(Namebuf,"8f7b076037390179c692d18b7d3b4e87b90ac1d192614d33a3f238cca69e9bd0");
	// printf("%s \n",Namebuf);

  //   // load pubkey
	// pubkey=Talloc0(sizeof(*pubkey));
	// if(pubkey==NULL)
	// 	return -ENOMEM;
	// ret=TCM_ExLoadTcmPubKey(pubkey,Namebuf);
	// if(ret!=0)
	// {
	// 	return -EINVAL;
	// }

  // get pub key from mem!!!!!!!!!!
//   DB_RECORD *db_record;
//   db_record = memdb_get_first(TYPE_PAIR(VTCM_IN_KEY,TCM_BIN_PUBKEY));
//   if(db_record == NULL){
//     return -EINVAL;
//   }

//   //printf("db_record is %x\n",db_record->record->algorithmParms);

//   db_record->record -= (0x7fffe000122a-0x7fffe0000a72);

//   tcm_pubkey = db_record->record;
    
//     printf("pubkey:%x \n",&(tcm_pubkey->algorithmParms));

	//print_cubeaudit("get pubkey %s succeed!\n",tcm_pubkey->pubKey);
	// printf("当前所在进程%d %d\n",getpid());
    int fd;
    char file_name[DIGEST_SIZE*4];
    BYTE * Buf;
	TCM_PUBKEY * pubkey;
 	//printf(" Strcpy：file_name\n");
    Strcpy(file_name,"./pub");
	fd=open(file_name,O_RDONLY);
	if(fd<0)
		return -EINVAL;
    Buf=Salloc0(DIGEST_SIZE);
	ret=read(fd,Buf,DIGEST_SIZE);
	close(fd);
    
	print_cubeaudit("get pubkey %s",Buf);

    Memset(Namebuf,0,DIGEST_SIZE*3);
	Strcpy(Namebuf,"pubkey/");
	Strcat(Namebuf,Buf);
//printf(" get tcmkey \n");
    printf("%s \n",Namebuf);

    // load pubkey
	pubkey=Talloc0(sizeof(*pubkey));
	if(pubkey==NULL)
		return -ENOMEM;
	ret=TCM_ExLoadTcmPubKey(pubkey,Namebuf);
	if(ret!=0)
	{
		return -EINVAL;
	}
	print_cubeaudit("get pubkey %s succeed!\n",Namebuf);
	
	print_cubeaudit("pubkey->pubKey:%x\n",pubkey->pubKey);

    printf("TCM_ExSM2Verify verify begin\n");
	

    // char a = *(char *)tcm_pubkey;
    // printf("hahahah %c\n",a);

	//printf("bin pubkey is : %s\n", tcm_pubkey->pubKey);
    // verify sign
    // for(; (void *)(tcm_pubkey_1+sizeof(tcm_pubkey)) != (void*)(tcm_pubkey+sizeof(tcm_pubkey));) {
    //   *tcm_pubkey_1++ = *tcm_pubkey++;
    // }

    //printf("tcm_pubkey_1 is : %x\n", tcm_pubkey_1);

    ret=TCM_ExSM2Verify(pubkey,sign_data->bindata,sign_data->size,blob,blob_size);
    printf("TCM_ExSM2Verify verify result is %d!\n",ret);
    
    // remove sign flag
    if(ret == 0){
    flag = message_get_flag(message);
    message_set_flag(message,flag|MSG_FLAG_VERIFY);
	}
    //output verify data
    verify_data=Talloc0(sizeof(*verify_data));
    verify_data->name = dup_str("verify_result",0);
    verify_data->return_value = ret;
    message_add_expand_data(message,TYPE_PAIR(VTCM_IN_KEY,TCM_BIN_PUBKEY),pubkey);

    ex_module_sendmsg(sub_proc,message);
    return ret;
}


// int  proc_memstore_pubkey(void *sub_proc, void *message) {
        
//       int ret;

// 	    MSG_EXPAND * msg_expand;
// 	    //RECORD(VTCM_IN_KEY,TCM_BIN_PUBKEY) * tcm_pubkey;

//       ret=message_get_record(message,&tcm_pubkey,0);

//       DB_RECORD *db_record;
//       db_record=memdb_store(tcm_pubkey,TYPE_PAIR(VTCM_IN_KEY,TCM_BIN_PUBKEY),NULL);
//       if(db_record==NULL)
//         return -EINVAL; 

//       return ret;
// }